package com.googlecode.etl.kravas;

import org.apache.commons.io.FilenameUtils;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import static org.apache.commons.io.FileUtils.forceMkdir;

/**
 * @author A_Reshetnikov
 * @since Date: 28.08.2013
 */
public class Main {

    private static boolean justPrintVersion;
    private static boolean justPrintUsage;
    private static String inputPath;
    private static String outputDirPath = "output";
    private static String filePath;
    private static String dirPath;
    private static String defaultConfigLocation = "applicationContext.xml";

    public static void main(String[] args) throws Exception {
        collectArgs(args);
        if (justPrintUsage) {
            printUsage();
            return;
        }

        if (justPrintVersion) {
            printVersion();
            return;
        }


        ConfigurableApplicationContext context = loadApplicationContext();

        modifyContext(context);

        List<String> filesToProcess = new ArrayList<String>();
        File f = new File(inputPath);
        if (!f.exists()) {
            throw new Exception(String.format("Input file or dir %s not exists:", inputPath));
        }
        if (f.isFile()) {
            filesToProcess.add(f.getAbsolutePath());
            System.out.println(String.format("Found 1 file for processing"));
        } else if (f.isDirectory()) {
            File[] arrayOfFiles = f.listFiles();
            if (arrayOfFiles.length == 0) {
                throw new Exception("Empty input directory:" + inputPath);
            }
            System.out.println(String.format("Found %d files for processing in directory %s", arrayOfFiles.length, inputPath));
            for (int i = 0; i < arrayOfFiles.length; i++) {
                filesToProcess.add(arrayOfFiles[i].getAbsolutePath());
            }
        }


        if (inputPath.equals(outputDirPath)) {
            throw new Exception("Input dir cannot be the same as output dir!");
        }

        prepateOutputDir();


        for (String fileName : filesToProcess) {
            new JobRunner().start(context, fileName, toOutputFileName(fileName));
        }


    }

    private static void prepateOutputDir() throws IOException {

        File dir = new File(outputDirPath);
        if (dir.exists() && !dir.isDirectory()) {
            throw new IOException("Cannot create dir");
        } else if (!dir.exists()) {
            forceMkdir(dir);
        }
    }

    private static String toOutputFileName(String fileName) throws IOException {
        return FilenameUtils.concat(outputDirPath, FilenameUtils.getName(fileName));

    }

    private static void modifyContext(ConfigurableApplicationContext context) {
        //todo implement modifyContext in Main
    }

    private static ConfigurableApplicationContext loadApplicationContext() {
        ConfigurableApplicationContext context = null;
//        if (customConfigLocation != null)
//            context = new FileSystemXmlApplicationContext(customConfigLocation);
//        else
        context = new ClassPathXmlApplicationContext(defaultConfigLocation);
        return context;
    }

    /**
     * Prints the usage information for this class to <code>System.out</code>.
     */
    private static void printUsage() {
        String lSep = System.getProperty("line.separator");
        StringBuffer msg = new StringBuffer();
        msg.append("java -jar etl-kravas.jar [-options]" + lSep);
        msg.append("Options: " + lSep);
        msg.append("  -i, --input [path]   path to file or directory with input files" + lSep);
        msg.append("  -o, --output [path]  path to output directory (default is ./output )" + lSep);
        msg.append("  -help, -h            print this message" + lSep);
        msg.append("  -version             print version info and exit" + lSep);
        System.out.println(msg.toString());
    }

    private static void collectArgs(String[] args) throws Exception {
        if (args.length == 0) {
            justPrintUsage = true;
            return;
        }

        for (int i = 0; i < args.length; i++) {
            String arg = args[i];
            if (arg.equals("-input") || arg.equals("-i") || arg.equals("--input")) {
                inputPath = args[i + 1];
                i++;
            } else if (arg.equals("-output") || arg.equals("-o") || arg.equals("--output")) {
                outputDirPath = args[i + 1];
                i++;
            } else if (arg.equals("-help") || arg.equals("-h") || arg.equals("--help")) {
                justPrintUsage = true;
            } else if (arg.equals("-version")) {
                justPrintVersion = true;
            } else if (arg.startsWith("-")) {
                // we don't have any more args to recognize!
                String msg = "Unknown argument: " + arg;
                System.err.println(msg);
                printUsage();
                throw new Exception("");
            }
        }
    }

    private static void printVersion() {
        System.out.println("etl-kravas version " + getVersion());
    }

    private static String getVersion() {
        return Main.class.getPackage().getImplementationVersion();
    }


}
